package top.codedance.iotp.client.net;

import cd.io.netty.bootstrap.ServerBootstrap;
import cd.io.netty.buffer.PooledByteBufAllocator;
import cd.io.netty.channel.ChannelFuture;
import cd.io.netty.channel.ChannelOption;
import cd.io.netty.channel.EventLoopGroup;
import cd.io.netty.channel.nio.NioEventLoopGroup;
import cd.io.netty.channel.socket.nio.NioServerSocketChannel;
import cd.io.netty.handler.logging.LogLevel;
import cd.io.netty.handler.logging.LoggingHandler;
import top.codedance.iotp.client.ClientApplication;
import top.codedance.iotp.client.net.configuration.HttpRouteConfig;
import org.apache.log4j.Logger;

import java.util.Arrays;

public class HttpServer implements Runnable {

    private static Logger logger = ClientApplication.getLogger(HttpServer.class);
    private int port = 10019;

    public HttpServer(int port){
        this.port = port;
    }

    @Override
    public void run() {
        AbstractHttpServer.httpRoutes.putAll(HttpRouteConfig.getConfig());
        EventLoopGroup boss = new NioEventLoopGroup(ClientApplication.ioThreads);
        EventLoopGroup httpWorker = new NioEventLoopGroup(ClientApplication.workerThreads);
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            ServerBootstrap group = bootstrap.group(boss, httpWorker);
            String logLevelArg = ClientApplication.commandCli.getArg("logLevel", "OFF");
            if(Arrays.asList(LogLevel.values(), String.class).contains(logLevelArg)) {
                group.handler(new LoggingHandler(LogLevel.valueOf(logLevelArg)));
            }
            group.channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 512)
                    .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childOption(ChannelOption.SO_RCVBUF, 128 * 1024)
                    .childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
                    .childHandler(new HttpPipelineInitializer());

            ChannelFuture channelFuture = bootstrap.bind(port).sync();
            if (channelFuture.isDone()) {
                ClientApplication.syslogInfo(String.format("Httpd API server bind port %s success", port));
            }
            /**CloseFuture异步方式关闭*/
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            logger.debug(e.getMessage());
        } finally {
            boss.shutdownGracefully();
            httpWorker.shutdownGracefully();
        }
    }
}
